package com.heima.service.impl;

import com.github.pagehelper.PageHelper;
import com.heima.constant.BaseContextConstant;
import com.heima.constant.DeptConstant;
import com.heima.context.BaseContext;
import com.heima.dto.DeptDto;
import com.heima.dto.pagedto.DeptPageDto;
import com.heima.entity.Dept;
import com.heima.mapper.DeptMapper;
import com.heima.result.Result;
import com.heima.service.DeptService;
import com.heima.vo.DeptNode;
import com.heima.vo.DeptVo;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Service
@RequiredArgsConstructor
public class DeptServiceImpl implements DeptService {
    private final DeptMapper deptMapper;

    @Override
    public void add(DeptDto deptDto) {

        // dept 传递字段 deptName, leader, email, phone, orderNum,  parentId, status
        Dept dept = new Dept();
        BeanUtils.copyProperties(deptDto, dept);

        // 处理 dto 数据类型与 dept 数据类型不一致
        dept.setOrderNum(Long.valueOf(deptDto.getOrderNum()));
        dept.setStatus(Integer.valueOf(deptDto.getStatus()));

        Long parentId = dept.getParentId();
        dept.setParentId(parentId);
        //  根据父部门 parent_id 查询父部门的的 parent_name
        String parentName = deptMapper.getParentByPrentId(parentId).getDeptName();
        dept.setParentName(parentName);
        // 查询祖宗部门的信息, 将id组成由逗号分隔的字符串  ancestors
        StringBuffer ancestorsWithComma = getAncestors(dept.getParentId());  // 最后查询结果会带有逗号, 需要去除
        StringBuffer ancestors = ancestorsWithComma.deleteCharAt(ancestorsWithComma.length() - 1);
        dept.setAncestors(String.valueOf(ancestors));
        //  del_flag 默认为 0
        dept.setDelFlag(DeptConstant.DEL_FLAG_NOT_DEL);
        // 创建者姓名、更新者姓名
        String currUser = BaseContext.getData(BaseContextConstant.USERNAME).toString();
        dept.setCreateBy(currUser);
        dept.setUpdateBy(currUser);

        deptMapper.add(dept);
    }

    @Override
    public List<DeptVo> pageQuery(DeptPageDto pageDto) {
        PageHelper.startPage(pageDto.getPageNum(), pageDto.getPageSize());
        List<Dept> deptList = deptMapper.pageQuery(pageDto);
        List<DeptVo> deptVoList = new ArrayList<>();
        for (Dept dept : deptList) {
            DeptVo deptVo = new DeptVo();
            BeanUtils.copyProperties(dept, deptVo);

            // 处理 字段名称 和 字段数据类型 不一致的数据
            deptVo.setDeptId(Math.toIntExact(dept.getId()));
            deptVo.setOrderNum(String.valueOf(dept.getOrderNum()));
            deptVo.setStatus(String.valueOf(dept.getStatus()));
            deptVo.setDelFlag(String.valueOf(dept.getDelFlag()));

            deptVoList.add(deptVo);
        }

        // todo 是否需要实现查询 用户 以及 子部门的功能
        return deptVoList;
    }

    @Override
    public DeptVo queryById(Long id) {
        Dept dept = deptMapper.queryById(id);
        DeptVo deptVo = new DeptVo();

        BeanUtils.copyProperties(dept, deptVo);

        // 处理 字段名称 和 字段数据类型 不一致的数据
        deptVo.setDeptId(Math.toIntExact(dept.getId()));
        deptVo.setOrderNum(String.valueOf(dept.getOrderNum()));
        deptVo.setStatus(String.valueOf(dept.getStatus()));
        deptVo.setDelFlag(String.valueOf(dept.getDelFlag()));

        return deptVo;
    }

    @Override
    public Result update(DeptDto deptDto) {
        Result result = new Result();
        // 如果该部门下存在子部门, 并且子部门中只要有一个部门为 启动, 则不能 停用部门
        // 其他操作不受影响
        List<Dept> allSubDeparts = getAllSubDepartments(deptDto.getDeptId());

        Integer updateStatus = Integer.parseInt(deptDto.getStatus());

        for (Dept dept : allSubDeparts) {
            if (dept == null) {
                break;
            }
            Integer status = dept.getStatus();
            if (DeptConstant.STATUS_SHUT_DOWN.equals(updateStatus) && status.equals(DeptConstant.STATUS_RUNNING)) {
                result.setMsg("该部门包含未停用的子部门!");
                result.setCode(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                return result;
            }
        }

        deptMapper.update(deptDto);
        result.setMsg("操作成功");
        result.setCode(HttpServletResponse.SC_OK);
        return result;
    }

    @Override
    public List<DeptNode> treeSelect() {
        List<DeptNode> tree = buildDeptTree(0L);
        return tree;
    }

    @Override
    public List<Dept> exclude(Integer id) {
        List<Dept> deptList = deptMapper.queryAllExceptSelf(id);
        return deptList;
    }

    @Override
    public Result deleteDept(Long id) {
        Result result = new Result();
        // 获取子部门信息
        List<Dept> allSubDepartments = getAllSubDepartments(id);
        if (!CollectionUtils.isEmpty(allSubDepartments)) {
            result.setMsg("部门存在子部门, 不允许删除");
            result.setCode(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            return result;
        }

        // todo 如果部门存在用户则不允许删除

        deptMapper.deleteDept(id);
        return Result.success();
    }


    /**
     * 根据 parentId 递归查询出 ancestors
     *
     * @param parentId
     * @return
     */
    public StringBuffer getAncestors(Long parentId) {
        StringBuffer sb = new StringBuffer();
        if (parentId != 0) {
            Long ancestorId = deptMapper.getParentByPrentId(parentId).getParentId();
            sb.append(getAncestors(ancestorId)); // 递归调用，获取上一级的祖先
            sb.append(parentId).append(","); // 将当前的parentId加入结果
        } else {
            sb.append("0,"); // 根节点
        }
        return sb;
    }


    /**
     * 获取部门的树状结构
     * @param parentId
     * @return
     */
    private List<DeptNode> buildDeptTree(Long parentId) {
        // 递归构建树的方法
        List<DeptNode> nodes = new ArrayList<>();

        // 获取具有给定 parentId 的部门
        List<Dept> depts = deptMapper.queryByParentId(parentId);

        for (Dept dept : depts) {
            DeptNode node = new DeptNode();
            node.setId(dept.getId());
            node.setLabel(dept.getDeptName());

            // 递归获取当前节点的子部门
            List<DeptNode> children = buildDeptTree(dept.getId());
            node.setChildren(children);

            nodes.add(node);
        }

        return nodes;
    }

    /**
     * 根据 部门 id 获取所有的子部门
     * @param deptId
     * @return
     */
    public List<Dept> getAllSubDepartments(Long deptId) {
        List<Dept> subDeptList = new ArrayList<>();
        Set<Long> visitedDeptIds = new HashSet<>(); // 用于防止循环引用

        // 创建一个栈，用于迭代地遍历部门树
        Stack<Long> stack = new Stack<>();
        stack.push(deptId); // 将起始部门 ID 压入栈

        while (!stack.isEmpty()) {
            Long currentId = stack.pop();

            // 检查是否已经访问过，防止循环引用
            if (visitedDeptIds.contains(currentId)) {
                continue;
            }
            visitedDeptIds.add(currentId);

            // 获取当前部门的信息（可选）
            Dept currentDept = deptMapper.queryById(currentId);
            if (currentDept != null && !currentId.equals(deptId)) {
                subDeptList.add(currentDept); // 将当前部门添加到结果列表（除起始部门外）
            }

            // 获取当前部门的直接子部门
            List<Dept> childDepts = deptMapper.queryByParentId(currentId);
            for (Dept dept : childDepts) {
                stack.push(dept.getId()); // 将子部门的 ID 压入栈，以便后续处理
            }
        }

        return subDeptList;
    }
}
